<?php
/**
 * AttendanceService.php
 *
 * @copyright   2023 thingsworld.com.cn - All Rights Reserved
 * @link        http://thingsworld.com.cn/
 * @author      stiffer.chen <chenl@thingsworld.com.cn>
 * @created     2023-04-09 10:50:11
 * @modified    2023-04-09 10:50:11
 *
 */

namespace App\Services;

use App\Models\CheckIn;
use App\Models\UserModel;
use App\Models\WorkOrder;
use Carbon\Carbon;
use Darabonba\GatewaySpi\Models\InterceptorContext\request;

class AttendanceService
{
    const CHECK_STATUS_IN = 'in';
    const CHECK_STATUS_OUT = 'out';

    public static function store()
    {
        $data = self::requestData();

        $id = $data['id'];
        $mainData = $data['main'];
        $workOrderIds = $data['work_order_ids'];
        if ($id) {
            $checkin = CheckIn::find($id);
        } else {
            $checkin = new CheckIn();
        }
        $workOrderIdsDb = [];
        foreach ($workOrderIds as $workOrderId) {
            $workOrderIdsDb[] = new CheckIn\WorkOrder([
                'work_order_id' => $workOrderId
            ]);
        }

        $checkin->fill($mainData);
        $checkin->saveOrFail();

        if ($workOrderIdsDb) {
            $checkin->work_orders()->delete();
            $checkin->work_orders()->saveMany($workOrderIdsDb);
        }

        return self::fetch($checkin->id);
    }

    public static function fetch($id)
    {
        $checkin = CheckIn::with(['work_orders.work_order'])->find($id);
        return self::getDetail($checkin);
    }

    public static function getListByWorkOrderId($workOrderId)
    {
        $workOrder = CheckIn\WorkOrder::byWorkOrderId($workOrderId)->get();
        $checkinIds = $workOrder->pluck('checkin_id')->toArray();

        $builder = CheckIn::with(['work_orders.work_order']);
        $builder->whereIn('id', $checkinIds);
        $data = $builder->get();
        $results = [];
        foreach ($data as $item) {
            $results[] = self::getDetail($item);
        }
        return $results;
    }

    public static function getList()
    {
        $perPage = intval(request()->get('limit') ?? 0);
        if (!$perPage) {
            $perPage = 10;
        }
        if ($perPage < 1) {
            $perPage = 10;
        }
        $signInDate = trim(strval(\request()->get('sign_in_date') ?? ''));
        $signInStart = $signInEnd = '';
        if ($signInDate) {
            try {
                $signInDate = Carbon::parse($signInDate)->toDateString();
                $signInStart = $signInDate . ' 00:00:00';
                $signInEnd = $signInDate . ' 23:59:59';
            } catch (\Exception $e) {
                throw new \Exception('签到日期格式错误');
            }
        }
        $name = \request()->get('name') ?? '';

        $builder = CheckIn::with(['work_orders.work_order']);
        if ($name) {
            $builder->where('user_name', 'like', "%{$name}%");
        }
        if ($signInStart) {
            $builder->where('checkin_time', '>=', $signInStart);
        }
        if ($signInEnd) {
            $builder->where('checkin_time', '<=', $signInEnd);
        }

        /**
         * 需要查看当前用户所在区域及所有子区域的签到数据
         * reason: http://pm.thingsworld.com.cn/index.php?m=task&f=view&taskID=402
         */

        $userId = intval(registry('user_id'));
        if ($userId) {
            $user = UserModel::find($userId);
            $deptId = $user->dept_id ?? 0;
            $userIds = self::getAllDeptUserIds($deptId);
            $userIds = array_unique(array_merge($userIds, [$userId]));
            $builder->whereIn('user_id', $userIds);
        }

        $builder->orderByDesc('update_time');
        $data = $builder->paginate($perPage);
        $data->transform(function ($item) {
            $itemDetail = self::getDetail($item);
            return $itemDetail;
        });
        return $data;
    }

    // 获取本区域及所有子级区域的用户ID
    private static function getAllDeptUserIds($deptId)
    {
        if (empty($deptId)) {
            return [];
        }
        // 获取子区域
        $childIds = (new DeptService())->getAllChildIds($deptId);
        return UserModel::query()->whereIn('dept_id', $childIds)->select(['id'])->pluck('id')->toArray();
    }

    private static function getDetail($checkin)
    {
        $workOrders = $checkin->work_orders;
        $workOrderData = [];
        foreach ($workOrders as $workOrder) {
            $workOrderData[] = [
                'id' => $workOrder->work_order->id,
                'wo_number' => $workOrder->work_order->wo_number
            ];
        }
        return [
            'id' => $checkin->id,
            'name' => $checkin->user_name,
            'check_status' => $checkin->check_status,
            'check_status_text' => $checkin->check_status_text,
            'checkin_time' => $checkin->checkin_time,
            'checkout_time' => $checkin->checkout_time,
            'checkin_address' => $checkin->checkin_address,
            'checkout_address' => $checkin->checkout_address,
            'checkin_img' => $checkin->checkin_img,
            'checkin_img_url' => $checkin->checkin_img_url,
            'checkout_img' => $checkin->checkout_img,
            'checkout_img_url' => $checkin->checkout_img_url,
            'rel_checkout_time' => $checkin->rel_checkout_time,
            'checkout_delay_desc' => $checkin->checkout_delay_desc,
            'work_time' => $checkin->work_time,
            'work_order_list' => $workOrderData
        ];
    }

    private static function requestData()
    {
        $allData = request()->getContent();
        $allArr = json_decode($allData, true);
        if (!$allArr) {
            throw new \Exception('操作失败，提交数据格式错误');
        }
        $checkStatus = strtolower($allArr['check_status'] ?? '');
        if (!in_array($checkStatus, [self::CHECK_STATUS_IN, self::CHECK_STATUS_OUT])) {
            throw new \Exception('签到状态错误');
        }
        $id = intval($allArr['id'] ?? 0);

        if ($id) {
            $checkin = CheckIn::find($id);
            if (empty($checkin)) {
                throw new \Exception("操作失败， 无签到数据: {$id}");
            }
        }

        if ($checkStatus == self::CHECK_STATUS_OUT && !$id) {
            throw new \Exception('签退时，打卡ID不能为空');
        }
        $checkinAddress = strtolower($allArr['checkin_address'] ?? '');
        $checkinImg = strtolower($allArr['checkin_img'] ?? '');
        $checkoutAddress = strtolower($allArr['checkout_address'] ?? '');
        $checkoutImg = strtolower($allArr['checkout_img'] ?? '');
        if ($checkStatus == self::CHECK_STATUS_IN) {
            if (!$checkinAddress) {
                throw new \Exception('签到时，请输入签到地址');
            }
            if (!$checkinImg) {
                throw new \Exception('签到时，请上传签到照片');
            }
        }
        if ($checkStatus == self::CHECK_STATUS_OUT) {
            if (!$checkoutAddress) {
                throw new \Exception('签退时，签退地址必填');
            }
            if (!$checkoutImg) {
                throw new \Exception('签退时，请上传签退照片');
            }
        }

        $checkInTime = strtolower($allArr['checkin_time'] ?? '');
        $checkOutTime = strtolower($allArr['checkout_time'] ?? '');
        $relCheckoutTime = strtolower($allArr['rel_checkout_time'] ?? '');

        if ($checkInTime != '') {
            try {
                $checkInTime = Carbon::parse($checkInTime)->toDateTimeString();
            } catch (\Exception $e) {
                throw new \Exception('签到时间错误');
            }
        }

        if ($checkOutTime != '') {
            try {
                $checkOutTime = Carbon::parse($checkOutTime)->toDateTimeString();
            } catch (\Exception $e) {
                throw new \Exception('签退时间错误');
            }
        }

        if ($relCheckoutTime != '') {
            try {
                $relCheckoutTime = Carbon::parse($relCheckoutTime)->toDateTimeString();
            } catch (\Exception $e) {
                throw new \Exception('真实签退时间错误');
            }
        }

        $checkoutDelayDesc = strtolower($allArr['checkout_delay_desc'] ?? '');

        $workOrderIds = array_unique($allArr['work_order_ids'] ?? []);
        if (!$workOrderIds && $checkStatus == self::CHECK_STATUS_IN) {
            throw new \Exception('数据错误, 无关联工单');
        }

        $workOrderIdArr = [];
        foreach ($workOrderIds as $workOrderId) {
            $workOrder = WorkOrder::find($workOrderId);
            if (empty($workOrder)) {
                throw new \Exception("数据错误, ID: {$workOrderId} 无对应工单");
            }
            $workOrderIdArr[] = $workOrderId;
        }
        if (empty($workOrderIdArr) && $checkStatus == self::CHECK_STATUS_IN) {
            throw new \Exception('操作失败，无关联工单');
        }

        $user = registry('user');
        $userId = $user->id ?? 0;
        $userName = $user->realname ?? '';

        $main = [];
        if ($checkinAddress) {
            $main['checkin_address'] = $checkinAddress;
        }
        if ($checkoutAddress) {
            $main['checkout_address'] = $checkoutAddress;
        }
        if ($checkinImg) {
            $main['checkin_img'] = $checkinImg;
        }
        if ($checkoutImg) {
            $main['checkout_img'] = $checkoutImg;
        }
        if ($checkStatus) {
            $main['check_status'] = $checkStatus;
        }
        if ($checkInTime) {
            $main['checkin_time'] = $checkInTime;
        }
        if ($checkOutTime) {
            $main['checkout_time'] = $checkOutTime;
        }
        if ($relCheckoutTime) {
            $main['rel_checkout_time'] = $relCheckoutTime;
        }
        if ($checkoutDelayDesc) {
            $main['checkout_delay_desc'] = $checkoutDelayDesc;
        }
        if ($userId) {
            $main['user_id'] = $userId;
        }
        if ($userName) {
            $main['user_name'] = $userName;
        }
        return [
            'id' => $id,
            'main' => $main,
            'work_order_ids' => $workOrderIdArr
        ];
    }
}